﻿
using hlog;
using hq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
namespace hconnect {
    // Token: 0x02000009 RID: 9
    public class SiemensConnect : SiemensConnectBase
    {
        const string write4CMD = "03 00 00 27 02 F0 80 32 01 00 00 99 99 00 0E 00 08 05 01 12 0A 10 02 00 04 {0} 84 00 {1} 00 04 00 20 {2}";
        //const string floatCMD= "03 00 00 27 02 F0 80 32 01 00 00 99 99 00 0E 00 08 05 01 12 0A 10 02 00 04 {0} 84 00 {1} 00 04 00 20 {2}";
        const string write2CMD = "03 00 00 25 02 F0 80 32 01 00 00 99 99 00 0E 00 06 05 01 12 0A 10 02 00 02 {0} 84 00 {1} 00 04 00 10 {2}";
        static byte[] header;
        byte iplast = 0;
        static SiemensConnect()
        {
            String text11 = "03 00 00 27 02 F0 80 32 01 00 00 99 99 00 0E 00 08 05 01 12 0A 10 02 00 04 0 1 84 00 00 00 00 04 00 20";
            header = Siemens102Util.StrToArraybyte(text11);
        }
        protected virtual int readMaxLen()
        {
            return 222;
        }
        protected override bool init()
        {
            base.init();
            iplast = (byte)int.Parse(ip.Substring(ip.LastIndexOf(".") + 1));
            return true;
        }
        public byte[] reader(int dbid, int startAddress, int readCount)
        {
            int max = readMaxLen();
            byte[] full = new byte[readCount];
            int offset = 0;
            lock (className)
            {
                if (noConn())
                {
                    return null;
                }
                do
                {
                    if (readCount > max)
                    {
                        byte[] b = read(dbid, startAddress, max);
                        if (b == null)
                        {
                            return null;
                        }
                        Array.Copy(b, 0, full, offset, b.Length);
                        offset += max;
                        startAddress += max;
                    }
                    else
                    {
                        byte[] b = read(dbid, startAddress, readCount);
                        if (b == null)
                        {
                            return null;
                        }
                        Array.Copy(b, 0, full, offset, b.Length);
                    }
                    readCount -= max;
                } while (readCount > 0);
                return full;
            }
        }
        //03 00 00 1F 02 F0 80 32 01 00 00 00 03 00 0E 00 00 04 01 12 0A 10 02 0 2a 1 F4 84 00 00 00
        //03 00 00 1F 02 F0 80 32 01 00 00 00 03 00 0E 00 00 04 01 12 0A 10 02 0 2a 1 F4 84 00 00 00
        private static Dictionary<long, byte[]> dict = new Dictionary<long, byte[]>();
        byte[] getByte(int dbid, int startAddress, int readCount)
        {
            long key = dbid * 10000000l + startAddress * 1000 + readCount;
            lock (dict)
            {
                if (!dict.ContainsKey(key))
                {
                    int begin = startAddress * 8;
                    byte[] b = new byte[] { 3, 0, 0, 0X1F, 2, 0XF0, 0X80, 0X32, 1, 0, 0, 0, iplast, 0, 0X0E, 0, 0, 4, 1, 0X12, 0X0A, 0X10, 2, 0, (byte)readCount, (byte)(dbid / 256), (byte)dbid, 0X84, 0, (byte)(begin / 256), (byte)begin };
                    dict.Add(key, b);
                }
                return dict[key];
            }
        }
        // 03   00   00   27    02  F0   80   32   01   00   00   99   99   00   0E   00   08   05   01   12   0A   10   02   00   04   0   1   84   00   0   78    00   04   00   20   0   0   0   1
        // 1     2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26  27  28   29   30   31   32   33   34   35  36   37               
        // -固定-   -报文长度- -------------固定---------------  --序号--  --固定--   -写入+4-  ----------固定--------  -byte -byte个数 ---db- -db-  ---偏移量---  -byte写-- -写入个数-
        //"03   00   00   25   02   F0   80   32   01   00   00   99   99   00   0E   00   06   05   01   12   0A   10   02   00   02   0   1   84   00   00   00   00   04   00   10   0   A"
        //"03   00   00   27   02   F0   80   32   01   00   00   99   99   00   0E   00   08   05   01   12   0A   10   02   00   04   0   1   84   00   00   00   00   04   00   20   7F  FF FF FF"
        public bool writeByteArr(short db, short addr, byte[] datas)
        {
            lock (className)
            {
                if (noConn())
                {
                    return false;
                }
                byte[] resArr = new byte[header.Length + datas.Length];
                header.CopyTo(resArr, 0);
                datas.CopyTo(resArr, header.Length);
                int len = datas.Length;
                resArr[2] = (byte)((35 + len) / 256);
                resArr[3] = (byte)((35 + len) % 256);
                resArr[15] = (byte)((4 + len) / 256);
                resArr[16] = (byte)((4 + len) % 256);
                resArr[23] = (byte)(len / 256);
                resArr[24] = (byte)(len % 256);
                resArr[25] = (byte)(db / 256);
                resArr[26] = (byte)(db % 256);
                addr *= 8;
                resArr[28] = (byte)(addr / 65536);
                resArr[29] = (byte)(addr % 65536 / 256);
                resArr[30] = (byte)(addr % 256);
                resArr[33] = (byte)((len * 8) / 256);
                resArr[34] = (byte)((len * 8) % 256);
                return sendOnce(resArr);
            }
        }
        public bool writeInt(short db, short addr, int data)
        {
            lock (className)
            {
                if (noConn())
                {
                    return false;
                }
                string text5 = Siemens102Util.ShortTOstr(db);//dbid
                string text6 = Siemens102Util.ShortTOstr(Convert.ToInt16((int)(addr * 8)));
                string text9 = Siemens102Util.IntTOstr(data);
                string text11 = string.Format(write4CMD, text5, text6, text9);
                return sendOnce(Siemens102Util.StrToArraybyte(text11));
            }
        }
        public bool writeFloat(short db, short addr, float data)
        {
            lock (className)
            {
                if (noConn())
                {
                    return false;
                }
              
                string text5 = Siemens102Util.ShortTOstr(db);//dbid
                string text6 = Siemens102Util.ShortTOstr(Convert.ToInt16((int)(addr * 8)));
                string text9 = Siemens102Util.FloatTOstr(data);

                string text11 = string.Format(write4CMD, text5, text6, text9);
                return sendOnce(Siemens102Util.StrToArraybyte(text11));
            }
        }

        public bool writeShort(short db, short addr, short data)
        {
            lock (className)
            {
                if (noConn())
                {
                    return false;
                }
                bool result = true;
                string text5 = Siemens102Util.ShortTOstr(db);//dbid
                short num = Convert.ToInt16(addr);
                string text6 = Siemens102Util.ShortTOstr(Convert.ToInt16((int)(num * 8)));
                string text9 = Siemens102Util.ShortTOstr(data);


                string text11 = string.Format(write2CMD, text5, text6, text9);
                return sendOnce(Siemens102Util.StrToArraybyte(text11));
            }
        }
        ///<summary >写入数据</summary>
        public bool writeByte(short db, short addr, byte data)
        {
            lock (className)
            {
                if (noConn())
                {
                    return false;
                }
                bool result = true;
                string text5 = Siemens102Util.ShortTOstr(db);//dbid
                short num = Convert.ToInt16(addr);
                string text6 = Siemens102Util.ShortTOstr(Convert.ToInt16((int)(num * 8)));
                string text9 = Siemens102Util.ByteTOstr(data);
                String key = "03 00 00 24 02 F0 80 32 01 00 00 99 99 00 0E 00 05 05 01 12 0A 10 02 00 01 {0} 84 00 {1} 00 04 00 08 {2}";
                string text11 = string.Format(key, text5, text6, text9);
                return sendOnce(Siemens102Util.StrToArraybyte(text11));
            }
        }
        byte[] read(int dbid, int startAddress, int readCount)
        {
            Send(getByte(dbid, startAddress, readCount));
            byte[] array = ReadTelex(readCount + 25);
            int num = array.Length;
            if (num == 19)
            {  //3 0 0 19 2 240 128 50  2 0 0 0 0 0 0 0 0 129 4

                if( array[12] == 220 ) {
                    LoggerCommon.fileAll("请检查：防护与安全》连接级制");
                } else {
                    LoggerCommon.fileAll("检查db块是否建立或者检查读取密码");
                }
               
                return null;
            }
            else if (num == 25)
            {
                LoggerCommon.fileAll("需要添加一个s7链接 ");//3 0 0 25 2 240  128 50 3 000 2 0 4 0 04 1 5 000
                return null;
            }
            else if (num == 25 + readCount)
            {
                return array.Skip(25).Take(readCount).ToArray();
            }
            else
            {
                return null;
            }
        }
        private bool sendOnce(byte[] packet)
        {
            Send(packet);
            byte[] array = ReadTelex(256);
            int num = array.Length;
            if (num == 22 && array[20] == 1 && array[21] == 255)
            {
                return true;
            }
            return false;
        }
    }
}